#include "StdAfx.h"
#include "DistinctivePoint.h"
#include "Stroke.h"
#include <GdiPlus.h>

const float kDrawingRadius = 3.0f;

int DistinctivePoint::sNextID = 0;

DistinctivePoint::DistinctivePoint()
	: mT(-1), mPrecision(-1), mID(++sNextID)
{
	mStrokePlaces.reserve(3);
}


void DistinctivePoint::SetPosition(float inX, float inY)
{
	mX = inX;
	mY = inY;
}

void DistinctivePoint::SetCurveParameter(float inT)
{
	mT = inT;
}

void DistinctivePoint::AddDirection(float inDx, float inDy,
	const Stroke* inStroke, int inStrokeEnd)
{
	float d = ::sqrt(inDx * inDx + inDy * inDy);
	StrokePlace place;
	place.strokePtr = inStroke;
	place.strokeID = inStroke->GetID();
	place.place = inStrokeEnd;
	place.vx = inDx / d;
	place.vy = inDy / d;
	mStrokePlaces.push_back(place);
}

bool DistinctivePoint::IsTPoint() const
{
	return (0 <= mT);
}

bool DistinctivePoint::IsCorner() const
{
	return  (2 == mStrokePlaces.size() && 0 > mT &&
		0 <= mStrokePlaces.front().place &&
		0 <= mStrokePlaces.back().place);
}

void DistinctivePoint::Draw(Gdiplus::Graphics& outGraphics, 
	Gdiplus::Pen& inPen, const Gdiplus::RectF& inRect) const
{
	if (mStrokePlaces.empty())
	{
		return;
	}
	Gdiplus::RectF r(mX - kDrawingRadius, mY - kDrawingRadius, 
		2 * kDrawingRadius, 2 * kDrawingRadius);
	if (r.IntersectsWith(inRect))
	{
		Gdiplus::Pen* semiTransparentPen = inPen.Clone();
		Gdiplus::Color color;
		inPen.GetColor(&color);
		Gdiplus::ARGB argb = color.GetValue();
		argb = (argb & 0xFFFFFF) | (128 << ALPHA_SHIFT);
		color.SetValue(argb);
		semiTransparentPen->SetColor(color);
		outGraphics.DrawEllipse(semiTransparentPen, r);
		delete semiTransparentPen;

		Gdiplus::PointF center(mX, mY);
		for (int i = mStrokePlaces.size(); i--;)
		{
			const StrokePlace& sp = mStrokePlaces[i];
			if (0 > sp.place)
			{
				Curve curve(mX, mY, sp.vx, sp.vy, sp.strokePtr, sp.place);
				Gdiplus::GraphicsPath path;
				curve.AddToPath(&path);
				outGraphics.DrawPath(&inPen, &path);
			}
			else
			{
				float x = mX + sp.vx * kDrawingRadius * 0.7f;
				float y = mY + sp.vy * kDrawingRadius * 0.7f;
				Gdiplus::PointF e(x, y);
				outGraphics.DrawLine(&inPen, center, e);
			}
		}
		if (IsTPoint())
		{
			// the first item is two-directional...
			float x = mX - mStrokePlaces.front().vx * kDrawingRadius * 0.7f;
			float y = mY - mStrokePlaces.front().vy * kDrawingRadius * 0.7f;
			Gdiplus::PointF e(x, y);
			outGraphics.DrawLine(&inPen, center, e);
		}
	}
}